/**
 * Software License, Version 1.0
 *
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 *
 *
 *Redistribution and use in source and binary forms, with or without
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For
 * further information contact the Community Grids Lab at
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and
 * wherever such third-party acknowledgments normally appear.
 *
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering,
 * shall not be used to endorse or promote products derived from this software
 * without prior written permission from Indiana University.  For written
 * permission, please contact the Advanced Research and Technology Institute
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering,
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 *
 *
 * Indiana University provides no reassurances that the source code provided
 * does not infringe the patent or any other intellectual property rights of
 * any other entity.  Indiana University disclaims any liability to any
 * recipient for claims brought by any other entity based on infringement of
 * intellectual property rights or otherwise.
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS.
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS",
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION
 *GENERATED USING SOFTWARE.
 */
package cgl.narada.samples.nbNative.tds;

/**
 * This class is adapted from cgl.narada.samples.rtp.NBRTPTransmitter. It uses
 * NBMediaConnector to transmit stream.
 * 
 * @author Hasan Bulut - hbulut@indiana.edu Community Grids Lab., Indiana
 *         University
 * @version 1.0
 */
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Properties;

import javax.media.CaptureDeviceInfo;
import javax.media.CaptureDeviceManager;
import javax.media.MediaLocator;
import javax.media.format.VideoFormat;
import javax.media.protocol.ContentDescriptor;
import javax.media.protocol.DataSource;
import javax.media.rtp.RTPConnector;
import javax.media.rtp.RTPManager;
import javax.media.rtp.SendStream;

import cgl.narada.samples.rtp.MediaCapturer;
import cgl.narada.service.ServiceException;

public class NBMediaTransmitter {

    private RTPManager rtpManager = null;

    private DataSource dataSource = null;

    private RTPConnector connector = null;

    public NBMediaTransmitter(RTPConnector connector) {
        this.connector = connector;
    }

    public void setDataSource(DataSource ds) {

        if (ds == null) {
            System.out.println("DataSource is null.");
            return;
        }

        if (this.dataSource != null) {
            System.out.println("datasource is already set.");
            return;
        }
        this.dataSource = ds;
    }

    public void close() {

        if (dataSource != null)
            dataSource.disconnect();

        if (rtpManager != null) {
            rtpManager.removeTargets("Session ended.");
            rtpManager.dispose();
            rtpManager = null;
        }
    }

    public String start() {
        try {
            rtpManager = RTPManager.newInstance();
            rtpManager.initialize(connector);
            SendStream sendStream = rtpManager.createSendStream(dataSource, 0);
            sendStream.start();
            System.out.println("Started transmitting data with the ssrc: "
                + sendStream.getSSRC());
        } catch (javax.media.format.UnsupportedFormatException e) {
            System.out
                .println(this.getClass().getName()
                    + "  Exception while trying to initialize rtp manager. The message is: "
                    + e.getMessage());
            System.out.println(this.getClass().getName()
                + "  the failed exception is: " + e.getFailedFormat());
            return e.getMessage();
        } catch (Exception e) {
            return e.getMessage();
        }
        return null;
    }

    public static void main(String args[]) throws Exception {
        if ((args.length < 4) || (args.length > 5)) {
            printUsage();
            return;
        }
        String brokerIP = args[0];
        int brokerPort = Integer.parseInt(args[1]);
        int topicNumber = Integer.parseInt(args[2]);
        String commType = args[3];
        MediaLocator ml = getMediaLocator();
        ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
        VideoFormat format = new VideoFormat(VideoFormat.H263_RTP);
        MediaCapturer mc = new MediaCapturer(ml, cd, format);
        // construct a clone for the datasource so that we can both play and
        // transmit it
        DataSource dataSource = mc.getDataSource();
        // dataSource =
        // javax.media.Manager.createCloneableDataSource(dataSource);
        // DataSource clonedDataSource =
        // ((SourceCloneable)dataSource).createClone();

        // play the video
        // new PlayerWindow(dataSource);

        // send the video
        Properties props = new Properties();
        props.put("hostname", brokerIP);
        props.put("portnum", args[1]);
        NBMediaConnector connector = new NBMediaConnector(brokerIP, brokerPort,
                                                          2, topicNumber);
        try {
            connector.initializeBrokerCommunications(props, commType);
            connector.initializeTransmitter();
            // connector.initializeReceiver();
        } catch (ServiceException ex) {
            ex.printStackTrace();
        }
        NBMediaTransmitter ct = new NBMediaTransmitter(connector);
        ct.setDataSource(dataSource);
        String result = ct.start();
        if (result != null) {
            System.err
                .println("Failed to initialize the transmitter. The message is: "
                    + result);
        } else {
            System.err
                .println("  - Started transmitting data to the topic: "
                    + topicNumber + " at the broker " + brokerIP + ":"
                    + brokerPort);
        }

        // start the receiver
        // NBMediaReceiver.startReceiver(connector);

        // wait indefinetely

        try {
            BufferedReader commandLine = new BufferedReader(
                                                            new InputStreamReader(
                                                                                  System.in));

            while (true) {
                String s = commandLine.readLine();
                if (s == null) {
                    System.out.println("Specified command is null! Exiting.");
                    ct.close();
                    break;
                }
                if (s.equals("h")) {
                    System.out
                        .println("\n\nComands for the NBMediaTransmitter:");
                    System.out
                        .println("s\t\t\t Stops the trasmitter and exits !!!");
                    System.out.println("p\t\t\t Pauses the transmitter");
                    System.out
                        .println("r\t\t\t Restarts the transmitter after pause");
                }
                if (s.equals("s")) {
                    ct.close();
                }
                if (s.equals("p")) {
                    // connector.setPublishEnabled(false);
                    dataSource.stop();
                }
                if (s.equals("r")) {
                    // connector.setPublishEnabled(true);
                    dataSource.start();
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    } // end of main

    public static void printUsage() {
        String usage = "Usage: java cgl.narada.samples.rtp.Transmitter "
            + " <Broker IP>   <Broker Port>   <Topic Number>";
        System.out.println(usage);
    }

    /**
     * get a MediaLocator from a capture device for video
     */
    public static MediaLocator getMediaLocator() {
        VideoFormat videoFormat = new VideoFormat(VideoFormat.YUV);
        java.util.Vector deviceList = CaptureDeviceManager
            .getDeviceList(videoFormat);
        MediaLocator ml = null;
        String debugInfo = null;
        if (deviceList.size() == 0) {
            debugInfo = "There is no video device on the computer OR "
                + "You did not run JMFRegistry \n"
                + "If you had installed JMF but did not run the JMFRegistry..."
                + "\n\t Please run JMFRegistry and try again "
                + "It's in the same folder as JMStudio in the Application menu";

            System.out.println(debugInfo);
        } else if (deviceList.size() == 1) {
            ml = ((CaptureDeviceInfo) deviceList.get(0)).getLocator();
        } else {
            System.out
                .println("There are more than one Video device on this machine.");
            System.out.println("We will try the first one");
            ml = ((CaptureDeviceInfo) deviceList.get(0)).getLocator();
        }
        return ml;
    }

}
